﻿using System;
using System.Linq;
using System.Text;

namespace Yaml.Presentation.Parsing.TokenScanners {
    abstract class AnchorTokenScannerBase : BasicTokenScanner {
        private string anchor;

        public AnchorTokenScannerBase(Scanner scanner, char indicator)
            : base(scanner, indicator) {
        }

        public string Anchor { get { return anchor; } }

        protected override void BeforeScan() {
            base.BeforeScan();
            // Could be a simple key
            SaveSimpleKey();
        }

        protected override void ScanForToken() {
            base.ScanForToken();
            ScanAnchor();
        }

        protected override void AfterScan() {
            base.AfterScan();
            // Can't have a simple key after this
            Scanner.State.SimpleKeys.IsSimpleKeyAllowed = false;
        }

        protected void ScanAnchor() {
            // Anchor can be alphanumeric characters (incl. _ and -)
            StringBuilder sb = new StringBuilder();
            char ch = Reader.Peek();
            while (Scanner.IsAlphanumeric(ch)) {
                sb.Append(ch);
                ch = Reader.PeekRelative(sb.Length);
            }
            if (sb.Length == 0) {
                throw GetAnchorScanException(ch);
            }
            Scanner.Forward(sb.Length);
            // Anchor must be followed by a space, linebreak or one of ?:,]}%@`
            if (!"\0 \t\r\n\x85\u2028\u2029?:,]}%@`".Contains(Reader.Peek())) {
                throw GetAnchorScanException(Reader.Peek());
            }
            anchor = sb.ToString();
        }

        protected Exception GetAnchorScanException(char ch) {
            return new ScannerException(
                "while scanning an " + this.GetType().Name.Replace("TokenScanner", "").ToLower() + " at " + Start.ToString() +
                "expected alphabetic or numeric character, but found " + ch + " at " + Scanner.GetMark().ToString());
        }

    }
}
